#include once <div32.asm>
;
__DIVF16:	; 16.16 Fixed point Division (signed)
; DE.HL = Dividend, Stack Top = Divisor
; A = Dividend, B = Divisor => A / B
lda z80_c            ;- exx
ldx z80_cp
stx z80_c
sta z80_cp
lda z80_b
ldx z80_bp
stx z80_b
sta z80_bp
lda z80_e
ldx z80_ep
stx z80_e
sta z80_ep
lda z80_d
ldx z80_dp
stx z80_d
sta z80_dp
lda z80_l
ldx z80_lp
stx z80_l
sta z80_lp
lda z80_h
ldx z80_hp
stx z80_h
sta z80_hp
pla                ;- pop hl   ; return address
sta z80_h
pla
sta z80_l
pla                ;- pop de   ; low part
sta z80_d
pla
sta z80_e
tsx                ;- ex (sp),hl   ;- CALLEE Convention ; H'L'D'E' => Dividend
lda $0103,x
ldy z80_h
sta z80_h
tya
sta $0103,x
lda $0104,x
ldy z80_l
sta z80_l
tya
sta $104,x
lda z80_e           ;- ex de,hl     ;- D'E'.H'L' Dividend
ldx z80_l
stx z80_e
sta z80_l
lda z80_d
ldx z80_h
stx z80_d
sta z80_h

__DIVF16START: ; FAST Entry: DEHL => Dividend, D'E'H'L' => Divisor
lda z80_d           ;- ld a,d	 ; Save sign
sta z80_a
ldx z80_ap          ;- ex af,af'
sta z80_ap
txa
lda z80_d           ;- bit 7,d ; Negative?
bit 7
beq *+5             ;- call nz, __NEG32 ; Negates DEHL
jsr __NEG32
lda z80_c           ;- exx		; Now works with D'E'.H'L'
ldx z80_cp
stx z80_c
sta z80_cp
lda z80_b
ldx z80_bp
stx z80_b
sta z80_bp
lda z80_e
ldx z80_ep
stx z80_e
sta z80_ep
lda z80_d
ldx z80_dp
stx z80_d
sta z80_dp
lda z80_l
ldx z80_lp
stx z80_l
sta z80_lp
lda z80_h
ldx z80_hp
stx z80_h
sta z80_hp
ldx z80_ap         ;- ex af,af'
sta z80_ap
txa
eor z80_d      ;- xor d
ldx z80_ap     ;- ex af,af'  ; Stores sign of the result for later
sta z80_ap
txa
lda z80_d      ;- bit 7,d ; Negative?
bit 7
beq *+5        ;- call nz, __NEG32
jsr __NEG32
lda z80_c      ;- exx		 ; Now we have DE.HL => Dividend
ldx z80_cp
stx z80_c
sta z80_cp
lda z80_b
ldx z80_bp
stx z80_b
sta z80_bp
lda z80_e
ldx z80_ep
stx z80_e
sta z80_ep
lda z80_d
ldx z80_dp
stx z80_d
sta z80_dp
lda z80_l
ldx z80_lp
stx z80_l
sta z80_lp
lda z80_h
ldx z80_hp
stx z80_h
sta z80_hp
lda %16              ;- ld b,16
sta z80_b

__SHIFTALOOP:
; Tries to shift Dividend to the left
lda z80_d            ;- bit 7,d
bit 7
jne __SHIFTB         ;- jp nz, __SHIFTB
asl z80_l            ;- add hl,hl
rol z80_h
lda z80_e            ;- ex_de_hl
ldx z80_l
stx z80_e
sta z80_l
lda z80_d
ldx z80_h
stx z80_d
sta z80_h
                     ;- adc hl,hl
lda z80_e            ;- ex_de_hl
ldx z80_l
stx z80_e
sta z80_l
lda z80_d
ldx z80_h
stx z80_d
sta z80_h
                     ;- djnz __SHIFTALOOP
jmp __DOF16_DIVRDY   ;- jp __DOF16_DIVRDY

__SHIFTB:
; Cannot shift Dividend more to the left, try to shift Divisor to the right
lda z80_b            ;- ld a,b
sta z80_a
lda z80_c            ;- exx
ldx z80_cp
stx z80_c
sta z80_cp
lda z80_b
ldx z80_bp
stx z80_b
sta z80_bp
lda z80_e
ldx z80_ep
stx z80_e
sta z80_ep
lda z80_d
ldx z80_dp
stx z80_d
sta z80_dp
lda z80_l
ldx z80_lp
stx z80_l
sta z80_lp
lda z80_h
ldx z80_hp
stx z80_h
sta z80_hp
lda z80_a              ;- ld b,a
sta z80_b
; Divisor is in DEHL
__SHIFTBLOOP:
                       ;- bit 1, l
jne __DOF16_DIVIDE     ;- jp nz, __DOF16_DIVIDE
                       ;- sra d
ror z80_e              ;- rr e
ror z80_h              ;- rr h
ror z80_l              ;- rr l
dec z80_b              ;- djnz __SHIFTBLOOP
jne __SHIFTBLOOP

__DOF16_DIVIDE:
lda z80_b              ;- ld a,b
sta z80_a
lda z80_c              ;- exx
ldx z80_cp
stx z80_c
sta z80_cp
lda z80_b
ldx z80_bp
stx z80_b
sta z80_bp
lda z80_e
ldx z80_ep
stx z80_e
sta z80_ep
lda z80_d
ldx z80_dp
stx z80_d
sta z80_dp
lda z80_l
ldx z80_lp
stx z80_l
sta z80_lp
lda z80_h
ldx z80_hp
stx z80_h
sta z80_hp
lda z80_a            ;- ld b,a
sta z80_b

__DOF16_DIVRDY:
lda z80_c            ;- exx
ldx z80_cp
stx z80_c
sta z80_cp
lda z80_b
ldx z80_bp
stx z80_b
sta z80_bp
lda z80_e
ldx z80_ep
stx z80_e
sta z80_ep
lda z80_d
ldx z80_dp
stx z80_d
sta z80_dp
lda z80_l
ldx z80_lp
stx z80_l
sta z80_lp
lda z80_h
ldx z80_hp
stx z80_h
sta z80_hp
lda z80_e          ;- ex de,hl
ldx z80_l
stx z80_e
sta z80_l
lda z80_d
ldx z80_h
stx z80_d
sta z80_h
lda z80_c          ;- push bc
pha
lda z80_b
pha
jsr __DIVU32START  ;- call __DIVU32START
pla                ;- pop bc
sta z80_b
pla
sta z80_c
eor z80_a          ;- xor a
ora z80_b          ;- or b
jmp __ENDF16DIV    ;- jp z,__ENDF16DIV

__SHIFTCLOOP:
asl z80_l          ;- add hl,hl	; Shift DECIMAL PART << 1
rol z80_h
lda z80_e          ;- ex_de_hl
ldx z80_l
stx z80_e
sta z80_l
lda z80_d
ldx z80_h
stx z80_d
sta z80_h
                   ;- adc hl,hl  ; Shift INTEGER PART << 1 Plus Carry
lda z80_e          ;- ex_de_hl
ldx z80_l
stx z80_e
sta z80_l
lda z80_d
ldx z80_h
stx z80_d
sta z80_h
dec z80_b      ;- djnz __SHIFTCLOOP
jne __SHIFTCLOOP

__ENDF16DIV: 	   ; Put the sign on the result
ldx z80_ap     ;- ex af, af' ; Recovers sign
sta z80_ap
txa
and #128       ;- and 128	   ; positive?
bne *+3        ;- ret z
rts
jcs __NEG32    ;- jp __NEG32 ; Negates DEHL and returns from there

